2023.6.1 最適化【torch】
# scipy.diff が廃止されていることに注意 (2024.7.10追記)
最急降下法を用いて2次関数の極値を求める。
目的関数$ f(x)=x^2、学習率 lr、探索の初期値x1 = 1.0とする。
code:python
import torch, numpy
import matplotlib.pyplot as plt
import scipy
def f(x):
return x**2
x1 = torch.tensor(1.0, dtype=torch.float, requires_grad=True) # (1)
lr = 0.1
x1data = []
x1grad = []
loopmax = 50
for i in range(loopmax):
y = f(x1) # (2)
y.backward() # (3)
x1data.append(x1.data.detach().numpy().copy())
x1grad.append(x1.grad.detach().numpy().copy())
x1.data = x1.data - lr*x1.grad
print(i, x1, x1.grad) # (4)
x1.grad.zero_()
x1data = numpy.array(x1data)
x1grad = numpy.array(x1grad)
plt.plot(x1data, f(x1data), 'x-')
x1data_d = scipy.diff(x1data)
vscale1 = x1data_d/1.5
ones = numpy.ones(loopmax - 1)
plt.quiver(x1data:-1, f(x1data:-1), ones*vscale1, x1grad:-1*vscale1, angles='xy', scale_units='xy', scale=1, color='red', width=0.005) plt.grid()
plt.show()
plt.plot(x1data)
plt.grid()
plt.show()
https://scrapbox.io/files/646ef3d82c17b0001c4e9e50.png
https://scrapbox.io/files/646ef3e0e1b611001cafb208.png
この問題をtorch.optimを用いて作り直してみる。
code:python
import torch, numpy
import matplotlib.pyplot as plt
import scipy
import torch.optim
def f(x):
return x**2
x1 = torch.tensor(1.0, dtype=torch.float32, requires_grad=True)
lr = 0.1
x1data = []
x1grad = []
loopmax = 50
optimizer = torch.optim.SGD(x1, lr=lr, momentum=0) # 最適化器の生成 for i in range(loopmax):
optimizer.zero_grad() # 勾配を0にする
y = f(x1)
y.backward() # 自動微分
optimizer.step() # 最適化器が指している変数を更新
x1data.append(x1.data.detach().numpy().copy())
x1grad.append(x1.grad.detach().numpy().copy())
print(i, x1, x1.grad)
x1data = numpy.array(x1data)
x1grad = numpy.array(x1grad)
plt.plot(x1data, f(x1data), 'x-')
x1data_d = scipy.diff(x1data)
vscale1 = x1data_d/1.5
ones = numpy.ones(loopmax - 1)
plt.quiver(x1data:-1, f(x1data:-1), ones*vscale1, x1grad:-1*vscale1, angles='xy', scale_units='xy', scale=1, color='red', width=0.005) plt.grid()
plt.show()
plt.plot(x1data)
plt.grid()
plt.show()
同様の結果が得られていることが確認できる。